package p_400

import com.sun.xml.internal.fastinfoset.util.StringArray
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.DatagramChannel
import java.nio.channels.SelectionKey
import java.nio.channels.Selector

/***
 * UDP echo 协议  使用通道实现
 */
class UDPEchoClientWithChannel {

    companion object {
        const val PORT = 7
        const val LIMIT = 100

        fun main(args: StringArray) {
            var remote: InetSocketAddress? = null
            try {
                remote = InetSocketAddress(args[0]!!, PORT)
                val channel = DatagramChannel.open()
                channel.configureBlocking(false)
                channel.connect(remote)

                val selector = Selector.open()
                channel.register(selector, SelectionKey.OP_READ or SelectionKey.OP_WRITE)

                val buffer = ByteBuffer.allocate(4)
                var n = 0
                var numbersRead = 0
                while (true) {
                    if (numbersRead == LIMIT) break
                    selector.select(60000)
                    val readyKeys = selector.selectedKeys()
                    if (readyKeys.isEmpty() && n == LIMIT) break
                    val iterator = readyKeys.iterator()

                    while (iterator.hasNext()) {
                        val key = iterator.next()
                        iterator.remove()
                        if (key.isReadable) {
                            buffer.clear()
                            channel.read(buffer)
                            buffer.flip()
                            val echo = buffer.int
                            println("echo -> $echo")
                            numbersRead++
                        }
                        if (key.isWritable) {
                            buffer.apply {
                                clear()
                                putInt(n)
                                flip()
                            }
                            channel.write(buffer)
                            println("wirte-> $n")
                            n++
                            if (n == LIMIT) key.interestOps(SelectionKey.OP_READ)
                        }
                    }

                }

            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
    }

}